1 Introduction

Linear regression is one of the simplest predictive modeling algorithms that can predict the value of the dependent variable by considering only one independent variable. The variable to be predicted is called the dependent variable. The variable used to predict the value of another variable is called the independent variable.

2 Defination

Linear regression is an algorithm that shows a linear relationship between an independent variable and a dependent variable.

3 Mathematical Formulas

Y is dependent variable β0 is bias term β1,β2,…βn are coefficient x1,x2,…xn are independent variable ε is random error

An example of inline equation \(y=\beta_0+\beta_1x_1+\cdots+\beta_kx_k+\epsilon\), where \(\epsilon \sim N(0, \sigma^2)\).

4 Assumptions associated with a linear regression model

  • Linearity: The relationship between X and the mean of Y is linear.
  • Homoscedasticity: The variance of residual is the same for any value of X.
  • Independence: Observations are independent of each other.
  • Normality: For any fixed value of X, Y is normally distributed.

5 Case example 1 Raw Data Table

penguins = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w03/w03-penguins.csv")

penguins.new <- na.omit(penguins)
 
penguins.new = 
  filter(penguins.new, (species == "Adelie" | species == "Gentoo")
            & (island == "Biscoe" | island == "Torgersen" ) 
            & (5000 > body_mass_g & body_mass_g > 3500) )

penguins.new$BMI <- penguins.new$body_mass_g/(4000)

penguins.new <- subset(penguins.new, select = -c(X,body_mass_g,sex,year ))

5.1 Descriptive Statistic & Variables Relationship

  • flip : Penguins flipper length (mm)
  • bill : Penguins bill length (mm)
  • BMI: Penguins body mass / 4000 (grams)
flip = summary(penguins.new$flipper_length_mm )

bill = summary(penguins.new$bill_length_mm )
BMI = summary(penguins.new$BMI )


list(flip = flip, bill = bill, BMI=BMI)
$flip
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  180.0   191.0   200.0   201.5   212.0   222.0 

$bill
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  33.50   39.55   42.70   42.46   45.75   49.60 

$BMI
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.8875  0.9719  1.0750  1.0697  1.1750  1.2437 
pen <- c("flipper_length_mm", "bill_length_mm", "BMI")
DB <- penguins.new[pen]
pairs(DB)

  • flipper_length_mm : Penguins flipper length (mm)
  • bill_length_mm : Penguins bill length (mm)
  • BMI: Penguins body mass / 4000 (grams)

From the above figure, it is positive linear relationship between flipper_length_mm and BMI. Moreover, it is positive linear relationship between bill_length_mm and BMI.

5.2 The relationship between Bill legnth and Flipper length across 2 species

pg.img <- "https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w03/img2/penguin.jpeg"
my.pg <- readJPEG(getURLContent(pg.img))
raster.pg <- as.raster(my.pg)

# Use the code in the precious section
Bill.length = penguins.new$bill_length_mm
Flipper.length = as.numeric(penguins.new$flipper_length_mm)
size.body = as.numeric(penguins.new$BMI)

species = penguins.new$species

## identifying the ID 
Adelie.id = which(species=="Adelie")  # value are case sensitive!
Gentoo.id = which(species=="Gentoo")


## making an empty plot: type = "n" ==> no point
plot(Bill.length, Flipper.length, main = "Bill legnth vs Flipper legnth across 2 species", type = "n" ,  xlab = "Bill legnth (mm)", ylab = "Flipper Length (mm)")

points(Bill.length[Adelie.id], Flipper.length[Adelie.id], 
       pch = 19, col = "purple", cex = size.body[Adelie.id])

points(Bill.length[Gentoo.id], Flipper.length[Gentoo.id], 
       pch = 19, col = "navy", cex = size.body[Gentoo.id])


legend("topleft", c("Adelie", "Gentoo"), 
                  col=c("purple", "navy"),
                  pch=c(19, 19))

#rasterImage(raster.pg,57,190,60,220)

# plot a regression line 
abline(lm(Flipper.length[Adelie.id]~Bill.length[Adelie.id]),col='purple') 

abline(lm(Flipper.length[Gentoo.id]~Bill.length[Gentoo.id]),col='navy') 

From above the figure, most Gentoo penguins have longer flipper and longer bill than Adelie penguins. In addition, there is a positive linear relationship between flipper length and bill length in both the Gentoo and Adelie penguin studies.

6 Case example 2 Raw Data Table

6.1 Data Preparation

There are 4 raw data available on the Github website, including incomes file, life expectancy years file, countries total file and population total file. In addition,incomes file, life expectancy years file and population total file have to transpose data files (from wide to long). Then, combine the four files into a final dataset by using PROC SQL.

#read data files from GitHub
I.P.P = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w05/income_per_person.csv")

L.E.Y = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w05/life_expectancy_years.csv")


countrytot = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w05/countries_total.csv")


poptot = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w05/population_total.csv")


#transpose data from wide to long

IPPlong <- melt(setDT(I.P.P),value.name = "income", id.vars = c("geo"), variable.name = "year")

LEYlong <- melt(setDT(L.E.Y),value.name = "life_expectancy", id.vars = c("geo"), variable.name = "year")

poptotlong <- melt(setDT(poptot),value.name = "pop_size", id.vars = c("geo"), variable.name = "year")


## remove string X
IPPlong$year<-gsub("X","",as.character(IPPlong$year))
LEYlong$year<-gsub("X","",as.character(LEYlong$year))
poptotlong$year<-gsub("X","",as.character(poptotlong$year))


#merge Income Per Person and Life Expectancy in Years 
LifeExpIncom <- merge(LEYlong, IPPlong, by = c("geo", "year"),
                      all = TRUE)

#Create database
con <- dbConnect(drv = SQLite(),
                 dbname = ":memory:")

#store sample data in database
dbWriteTable(conn = con, 
             name = "LEYlong",
             value = LEYlong)

dbWriteTable(conn = con, 
             name = "IPPlong",
             value = IPPlong)

dbWriteTable(conn = con, 
             name = "LifeExpIncom",
             value = LifeExpIncom)

dbWriteTable(conn = con, 
             name = "countrytot",
             value = countrytot)

dbWriteTable(conn = con, 
             name = "poptotlong",
             value = poptotlong)

SELECT a.*, b.region
FROM LifeExpIncom AS A
LEFT JOIN countrytot AS B
ON A.geo = B.name;
#store sample data in database
dbWriteTable(conn = con, 
             name = "life2",
             value = life2)
SELECT a.*, b.pop_size
FROM life2 AS A
LEFT JOIN poptotlong AS B
ON A.geo = B.geo AND A.year = B.year ;
# write final data to csv file
write.csv(x = final, file = "final.csv", row.names = FALSE)
# read final file
final = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w05/final.csv")


data2015 <- filter(final,year==2015)  # create 2015data

data2015$size000 <- data2015$pop_size/20000000 

6.2 Descriptive Study Purpose & Variables Relationship

The study focus on the relationship between income and life expectancy across region in 2015. Secondary understanding of the relationship between income and life expectancy over year in different regions. There are 7 variables in final dataset.

  • geo : geography
  • pop_size : population size
  • size000 : equivalent ratio to population size

The below is the data table for 2015.

summary(data2015)
     geo                 year      life_expectancy     income      
 Length:193         Min.   :2015   Min.   :49.60   Min.   :   623  
 Class :character   1st Qu.:2015   1st Qu.:66.05   1st Qu.:  3290  
 Mode  :character   Median :2015   Median :73.30   Median : 11000  
                    Mean   :2015   Mean   :71.93   Mean   : 17433  
                    3rd Qu.:2015   3rd Qu.:77.50   3rd Qu.: 24100  
                    Max.   :2015   Max.   :83.80   Max.   :120000  
                                   NA's   :6                       
    region             pop_size            size000        
 Length:193         Min.   :1.100e+04   Min.   : 0.00055  
 Class :character   1st Qu.:1.990e+06   1st Qu.: 0.09950  
 Mode  :character   Median :8.550e+06   Median : 0.42750  
                    Mean   :3.807e+07   Mean   : 1.90340  
                    3rd Qu.:2.760e+07   3rd Qu.: 1.38000  
                    Max.   :1.400e+09   Max.   :70.00000  
                                                          

People with a maximum income of 120000 and a minimum income of 623 in 2015. Also, in 2015, people’s life expectancy index ranged from a high of 83.8 to a low of 49.6.

6.3 The Distribuition of Region in 2015

Asia has the highest percentage of the world’s population (28.5%), with a total of 51 countries. Oceania has the lowest percentage of the world’s population (7.26%), with a total of 13 countries.

piedata <- filter(data2015,!is.na(region))

piedataf = data.frame(cate =as.vector(unique(piedata$region)), 
                     freq = as.vector(table(piedata$region)))

# define a color vector
colors <- c('rgb(211,94,96)', 'rgb(128,133,133)', 'rgb(144,103,167)')
# make a pie chart
plot_ly(piedataf, 
        labels = ~cate, 
        values = ~freq, 
        type = 'pie',
        textposition = 'inside',
        textinfo = 'label + percent',
        insidetextfont = list(color = '#FFFFFF'),
        #hoverinfo = 'text',
        marker = list(colors = colors,
                      line = list(color = '#FFFFFF', width = 1)),
                      #The 'pull' attribute can also be used to create space between the sectors
        showlegend = TRUE) %>% 
         layout(title = 'Distribution of Region in 2015',
                xaxis = list(showgrid = FALSE, zeroline = FALSE, 
                             showticklabels = FALSE),
                yaxis = list(showgrid = FALSE, zeroline = FALSE, 
                             showticklabels = FALSE),
                      ## margin of the plot
      margin = list(
              b = 50,
              l = 100,
              t = 120,
              r = 50
      ))

6.4 The relationship between Income and Life Expectancy across Region in 2015

Most people in the European region have higher incomes and higher levels of life expectancy. And most people in the African region have lower incomes and lower levels of life expectancy.

plot_ly(
    data = data2015,
    x = ~income,  # Horizontal axis 
    y = ~life_expectancy,   # Vertical axis 
    color = ~factor(region),  # must be a numeric factor
    
    #text = ~Species,
    text = ~paste("country name: ", geo,
                   "<br>population size: ", pop_size,
                   "<br>region: ", region), 
     # Show the species in the hover text
     ## using the following hovertemplate() to add the information of the
     ## Two numerical variables to the hover text.
     ### Use the following hover template to display more information
     hovertemplate = paste('<i><b>life expectancy<b></i>: %{y}',
                           '<br><b>income</b>:  %{x}',
                           '<br><b>%{text}</b>'),
     alpha  = 0.6,
     marker = list(size = ~size000, sizeref = .05, sizemode = 'area' ),
     type = "scatter",
     mode = "markers",
     ## graphic size
     width = 700,
     height = 500) %>%
    layout(  
      ### Title 
      title =list(text = "Income vs Life Expectancy in 2015", 
                  font = list(family = "Times New Roman",  # HTML font family  
                                size = 18,
                               color = "red")), 
      ### legend
      legend = list(title = list(text = 'region',
                                 font = list(family = "Courier New",
                                               size = 14,
                                              color = "green")),
                    bgcolor = "ivory",
                    bordercolor = "navy",
                    groupclick = "togglegroup",  # one of  "toggleitem" AND "togglegroup".
                    orientation = "v"  # Sets the orientation of the legend.
                    ),
      ## margin of the plot
      margin = list(
              b = 100,
              l = 100,
              t = 50,
              r = 50
      ),
      ## Background
      plot_bgcolor ='#f7f7f7', 
      ## Axes labels
             xaxis = list( 
                    title=list(text = 'Income',
                               font = list(family = 'Arial')),
                    zerolinecolor = 'red', 
                    zerolinewidth = 2, 
                    gridcolor = 'white'), 
            yaxis = list( 
                    title=list(text = 'Life Expectancy',
                               font = list(family = 'Arial')),
                    zerolinecolor = 'purple', 
                    zerolinewidth = 2, 
                    gridcolor = 'white'),
       ## annotations
       annotations = list(  
                     x = 0.5,   # between 0 and 1. 0 = left, 1 = right
                     y = 1.5,   # between 0 and 1, 0 = bottom, 1 = top
                  font = list(size = 12,
                              color = "darkred"),   
                  text = "The point size is proportional to the population size",   
                  xref = "paper",  # "container" spans the entire `width` of the 
                                   #  lot. "paper" refers to the width of the 
                                   #  plotting area only. yref = "paper",  
                                   #  same as xref.
               xanchor = "center", #  horizontal alignment with respect to its x position
               yanchor = "bottom", #  similar to xanchor  
             showarrow = FALSE)
    
     
    
    ) 

6.5 The relationship between Income and Life Expectancy across Region over the years

The life expectancy of people in the all regions has increased with each passing year. In 1800, most of Europe had a higher level of life expectancy. However, in 2018, higher levels of life expectancy may come from multiple regional of country. As can be seen from the figure, there is a positive linear relationship between income and levels of life expectancy across regions.

pal.IBM <- c("#332288", "#117733", "#0072B2","#D55E00", "#882255")
pal.IBM <- setNames(pal.IBM, c("Asia", "Europe", "Africa", "Americas", "Oceania"))

df <- filter(final,!is.na(region))

#df <- final 
fig <- df %>%
  plot_ly(
    x = ~income, 
    y = ~life_expectancy, 
    size = ~(2*log(pop_size)-11)^2,
    color = ~region, 
    colors = pal.IBM,   # custom colors
    #marker = list(size = ~(log(pop)-10),  sizemode = 'area'),
    frame = ~year,      # the time variable to
    # to display in the hover
    text = ~paste("Country:", geo,
                  "<br>Region:", region,
                  "<br>Year:", year,
                  "<br>LifeExp:", life_expectancy,
                  "<br>Pop:", pop_size),
    hoverinfo = "text",
    type = 'scatter',
    mode = 'markers'
  )
fig <- fig %>% layout(
    xaxis = list(
      type = "log"
    ),
    
      title =list(text = "Income vs Life Expectancy over the years", 
                  font = list(family = "Times New Roman",  # HTML font family  
                                size = 18,
                               color = "red")),
    
      xaxis = list( 
                    title=list(text = 'Income',
                               font = list(family = 'Arial')),
                    zerolinecolor = 'red', 
                    zerolinewidth = 2, 
                    gridcolor = 'white'), 
            yaxis = list( 
                    title=list(text = 'Life Expectancy',
                               font = list(family = 'Arial')),
                    zerolinecolor = 'purple', 
                    zerolinewidth = 2, 
                    gridcolor = 'white')
  )

fig
LS0tDQp0aXRsZTogIlByZXNlbnRhdGlvbiBMaW5lYXIgUmVncmVzc2lvbiINCmF1dGhvcjogIkd1YW4gVHNlcm4gS3VvIg0KZGF0ZTogIldlc3QgQ2hlc3RlciBVbml2ZXJzaXR5Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgdGhlbWU6IGx1bWVuDQplZGl0b3Jfb3B0aW9uczoNCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KLyogVGFibGUgb2YgY29udGVudCAtIG5hdmlnYXRpb24gKi8NCmRpdiNUT0MgbGkgew0KICAgIGxpc3Qtc3R5bGU6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLWNvbG9yOmxpZ2h0Z3JheTsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQogICAgZm9udC1mYW1pbHk6IEFyaWFsLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWY7DQogICAgY29sb3I6ICM3ODBjMGM7DQp9DQoNCg0KLyogVGl0bGUgZm9udHMgKi8NCmgxLnRpdGxlIHsNCiAgZm9udC1zaXplOiAyNHB4Ow0KICBjb2xvcjogZGFya2JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6IEFyaWFsLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWY7DQogIGZvbnQtdmFyaWFudC1jYXBzOiBub3JtYWw7DQp9DQpoNC5hdXRob3IgeyANCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsNCiAgY29sb3I6IG5hdnk7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmRhdGUgeyANCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsNCiAgY29sb3I6IGRhcmtibHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCi8qIFNlY3Rpb24gaGVhZGVycyAqLw0KaDEgew0KICAgIGZvbnQtc2l6ZTogMjJweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMiB7DQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgDQogICAgZm9udC1zaXplOiAxNXB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsNCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogRGVjb3JhdGlvbiBvZiBoeXBlcmxpbmtzICAqLw0KDQovKiB1bnZpc2l0ZWQgbGluayAqLw0KYTpsaW5rIHsNCiAgY29sb3I6IGdyZWVuOw0KfQ0KDQovKiB2aXNpdGVkIGxpbmsgKi8NCmE6dmlzaXRlZCB7DQogIGNvbG9yOiBwdXJwbGU7DQp9DQoNCi8qIG1vdXNlIG92ZXIgbGluayAqLw0KYTpob3ZlciB7DQogIGNvbG9yOiByZWQ7DQp9DQoNCi8qIHNlbGVjdGVkIGxpbmsgKi8NCmE6YWN0aXZlIHsNCiAgY29sb3I6IHllbGxvdzsNCn0NCjwvc3R5bGU+DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImdhcG1pbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJnYXBtaW5kZXIiKQ0KICAgbGlicmFyeShnYXBtaW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHlyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInRpZHlyIikNCiAgIGxpYnJhcnkodGlkeXIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICAgbGlicmFyeSh0aWR5dmVyc2UpDQp9DQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoImNvd3Bsb3QiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiY293cGxvdCIpDQogICBsaWJyYXJ5KGNvd3Bsb3QpDQp9DQppZiAoIXJlcXVpcmUoImxhdGV4MmV4cCIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJsYXRleDJleHAiKQ0KICAgbGlicmFyeShsYXRleDJleHApDQp9DQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICAgbGlicmFyeShwbG90bHkpDQp9DQppZiAoIXJlcXVpcmUoImdhcG1pbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJnYXBtaW5kZXIiKQ0KICAgbGlicmFyeShnYXBtaW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoInBuZyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygicG5nIikgICAgICAgICAgICAgIyBJbnN0YWxsIHBuZyBwYWNrYWdlDQogICAgbGlicmFyeSgicG5nIikNCn0NCmlmICghcmVxdWlyZSgiUkN1cmwiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoIlJDdXJsIikgICAgICAgICAgICAgIyBJbnN0YWxsIFJDdXJsIHBhY2thZ2UNCiAgICBsaWJyYXJ5KCJSQ3VybCIpDQp9DQppZiAoIXJlcXVpcmUoImNvbG91cnBpY2tlciIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiY29sb3VycGlja2VyIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImNvbG91cnBpY2tlciIpDQp9DQppZiAoIXJlcXVpcmUoImdnYW5pbWF0ZSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dhbmltYXRlIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdnYW5pbWF0ZSIpDQp9DQppZiAoIXJlcXVpcmUoImdpZnNraSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2lmc2tpIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdpZnNraSIpDQp9DQppZiAoIXJlcXVpcmUoIm1hZ2ljayIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibWFnaWNrIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoIm1hZ2ljayIpDQp9DQppZiAoIXJlcXVpcmUoImdyRGV2aWNlcyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ3JEZXZpY2VzIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdyRGV2aWNlcyIpDQp9DQppZiAoIXJlcXVpcmUoImpwZWciKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImpwZWciKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgianBlZyIpDQp9DQppZiAoIXJlcXVpcmUoIlZHQU0iKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoIlZHQU0iKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiVkdBTSIpDQp9DQppZiAoIXJlcXVpcmUoIk1BU1MiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoIk1BU1MiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiTUFTUyIpDQp9DQppZiAoIXJlcXVpcmUoIm5uZXQiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoIm5uZXQiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgibm5ldCIpDQp9DQppZiAoIXJlcXVpcmUoImNsdXN0ZXIiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImNsdXN0ZXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiY2x1c3RlciIpDQp9DQppZiAoIXJlcXVpcmUoImRwbHlyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJkcGx5ciIpDQp9DQppZiAoIXJlcXVpcmUoIm9kYmMiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygib2RiYyIpDQogICBsaWJyYXJ5KG9kYmMpDQp9DQppZiAoIXJlcXVpcmUoIkRCSSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJEQkkiKQ0KICAgbGlicmFyeShEQkkpDQp9DQppZiAoIXJlcXVpcmUoIlJTUUxpdGUiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiUlNRTGl0ZSIpDQogICBsaWJyYXJ5KFJTUUxpdGUpDQp9DQoNCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCmlmICghcmVxdWlyZSgiZGF0YS50YWJsZSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJkYXRhLnRhYmxlIikNCiAgIGxpYnJhcnkoZGF0YS50YWJsZSkNCn0NCg0KDQojIGtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIkM6XFxTVEE0OTBcXHcwNSIpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEpDQoNCmRiIDwtIGRiQ29ubmVjdChSU1FMaXRlOjpTUUxpdGUoKSwgZGJuYW1lID0gInNxbC5zcWxpdGUiKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNvbm5lY3Rpb24gPSAiZGIiKQ0KDQoNCmBgYA0KDQoNCiMgSW50cm9kdWN0aW9uIA0KDQpMaW5lYXIgcmVncmVzc2lvbiBpcyBvbmUgb2YgdGhlIHNpbXBsZXN0IHByZWRpY3RpdmUgbW9kZWxpbmcgYWxnb3JpdGhtcyB0aGF0IGNhbiBwcmVkaWN0IHRoZSB2YWx1ZSBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGJ5IGNvbnNpZGVyaW5nIG9ubHkgb25lIGluZGVwZW5kZW50IHZhcmlhYmxlLiBUaGUgdmFyaWFibGUgdG8gYmUgcHJlZGljdGVkIGlzIGNhbGxlZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBUaGUgdmFyaWFibGUgdXNlZCB0byBwcmVkaWN0IHRoZSB2YWx1ZSBvZiBhbm90aGVyIHZhcmlhYmxlIGlzIGNhbGxlZCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUuDQoNCg0KDQojIERlZmluYXRpb24NCg0KTGluZWFyIHJlZ3Jlc3Npb24gaXMgYW4gYWxnb3JpdGhtIHRoYXQgc2hvd3MgYSBsaW5lYXIgcmVsYXRpb25zaGlwICAgIGJldHdlZW4gYW4gaW5kZXBlbmRlbnQgdmFyaWFibGUgYW5kIGEgZGVwZW5kZW50IHZhcmlhYmxlLg0KDQoNCmBgYHtyICxlY2hvID0gRkFMU0V9DQprbml0cjo6IGluY2x1ZGVfZ3JhcGhpY3MoImxpbi5naWYiKQ0KYGBgDQoNCg0KIyBNYXRoZW1hdGljYWwgRm9ybXVsYXMNCg0KWSBpcyBkZXBlbmRlbnQgdmFyaWFibGUNCs6yMCBpcyBiaWFzIHRlcm0NCs6yMSzOsjIsLi4uzrJuIGFyZSBjb2VmZmljaWVudA0KeDEseDIsLi4ueG4gYXJlIGluZGVwZW5kZW50IHZhcmlhYmxlDQrOtSBpcyByYW5kb20gZXJyb3INCg0KQW4gZXhhbXBsZSBvZiBpbmxpbmUgZXF1YXRpb24gJHk9XGJldGFfMCtcYmV0YV8xeF8xK1xjZG90cytcYmV0YV9reF9rK1xlcHNpbG9uJCwgd2hlcmUgJFxlcHNpbG9uIFxzaW0gTigwLCBcc2lnbWFeMikkLg0KDQojICBBc3N1bXB0aW9ucyBhc3NvY2lhdGVkIHdpdGggYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0KDQotIExpbmVhcml0eTogVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIFggYW5kIHRoZSBtZWFuIG9mIFkgaXMgbGluZWFyLg0KLSBIb21vc2NlZGFzdGljaXR5OiBUaGUgdmFyaWFuY2Ugb2YgcmVzaWR1YWwgaXMgdGhlIHNhbWUgZm9yIGFueSB2YWx1ZSBvZiBYLg0KLSBJbmRlcGVuZGVuY2U6IE9ic2VydmF0aW9ucyBhcmUgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlci4NCi0gTm9ybWFsaXR5OiBGb3IgYW55IGZpeGVkIHZhbHVlIG9mIFgsIFkgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNCg0KDQojIENhc2UgZXhhbXBsZSAxIFJhdyBEYXRhIFRhYmxlICAgDQoNCmBgYHtyfQ0KcGVuZ3VpbnMgPSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0dVQU5UU0VSTi1LVU8vd2ViY3YvbWFpbi93MDMvdzAzLXBlbmd1aW5zLmNzdiIpDQoNCnBlbmd1aW5zLm5ldyA8LSBuYS5vbWl0KHBlbmd1aW5zKQ0KIA0KcGVuZ3VpbnMubmV3ID0gDQogIGZpbHRlcihwZW5ndWlucy5uZXcsIChzcGVjaWVzID09ICJBZGVsaWUiIHwgc3BlY2llcyA9PSAiR2VudG9vIikNCiAgICAgICAgICAgICYgKGlzbGFuZCA9PSAiQmlzY29lIiB8IGlzbGFuZCA9PSAiVG9yZ2Vyc2VuIiApIA0KICAgICAgICAgICAgJiAoNTAwMCA+IGJvZHlfbWFzc19nICYgYm9keV9tYXNzX2cgPiAzNTAwKSApDQoNCnBlbmd1aW5zLm5ldyRCTUkgPC0gcGVuZ3VpbnMubmV3JGJvZHlfbWFzc19nLyg0MDAwKQ0KDQpwZW5ndWlucy5uZXcgPC0gc3Vic2V0KHBlbmd1aW5zLm5ldywgc2VsZWN0ID0gLWMoWCxib2R5X21hc3NfZyxzZXgseWVhciApKQ0KDQpgYGAgDQogDQoNCg0KYGBge3IgZXZhbD1yZXF1aXJlTmFtZXNwYWNlKCJEVCIsIHF1aWV0bHk9VFJVRSksIGVjaG89RkFMU0V9DQpEVDo6ZGF0YXRhYmxlKChwZW5ndWlucy5uZXcpLCBmaWxsQ29udGFpbmVyID0gRkFMU0UsIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSA2KSkNCg0KDQpgYGANCg0KIyMgRGVzY3JpcHRpdmUgU3RhdGlzdGljICYgVmFyaWFibGVzIFJlbGF0aW9uc2hpcCANCg0KLSBmbGlwIDogUGVuZ3VpbnMgZmxpcHBlciBsZW5ndGggKG1tKQ0KLSBiaWxsIDogUGVuZ3VpbnMgYmlsbCBsZW5ndGggKG1tKQ0KLSBCTUk6IFBlbmd1aW5zIGJvZHkgbWFzcyAvIDQwMDAgKGdyYW1zKQ0KDQoNCmBgYHtyfQ0KZmxpcCA9IHN1bW1hcnkocGVuZ3VpbnMubmV3JGZsaXBwZXJfbGVuZ3RoX21tICkNCg0KYmlsbCA9IHN1bW1hcnkocGVuZ3VpbnMubmV3JGJpbGxfbGVuZ3RoX21tICkNCkJNSSA9IHN1bW1hcnkocGVuZ3VpbnMubmV3JEJNSSApDQoNCg0KbGlzdChmbGlwID0gZmxpcCwgYmlsbCA9IGJpbGwsIEJNST1CTUkpDQoNCnBlbiA8LSBjKCJmbGlwcGVyX2xlbmd0aF9tbSIsICJiaWxsX2xlbmd0aF9tbSIsICJCTUkiKQ0KREIgPC0gcGVuZ3VpbnMubmV3W3Blbl0NCnBhaXJzKERCKQ0KYGBgDQoNCi0gZmxpcHBlcl9sZW5ndGhfbW0gOiBQZW5ndWlucyBmbGlwcGVyIGxlbmd0aCAobW0pDQotIGJpbGxfbGVuZ3RoX21tIDogUGVuZ3VpbnMgYmlsbCBsZW5ndGggKG1tKQ0KLSBCTUk6IFBlbmd1aW5zIGJvZHkgbWFzcyAvIDQwMDAgKGdyYW1zKQ0KDQpGcm9tIHRoZSBhYm92ZSBmaWd1cmUsIGl0IGlzIHBvc2l0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiBmbGlwcGVyX2xlbmd0aF9tbSBhbmQgQk1JLiBNb3Jlb3ZlciwgaXQgaXMgcG9zaXRpdmUgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGJpbGxfbGVuZ3RoX21tIGFuZCBCTUkuIA0KDQojIyAgIFRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBCaWxsIGxlZ250aCBhbmQgRmxpcHBlciBsZW5ndGggYWNyb3NzIDIgc3BlY2llcw0KDQpgYGB7cn0NCg0KIA0KcGcuaW1nIDwtICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vR1VBTlRTRVJOLUtVTy93ZWJjdi9tYWluL3cwMy9pbWcyL3Blbmd1aW4uanBlZyINCm15LnBnIDwtIHJlYWRKUEVHKGdldFVSTENvbnRlbnQocGcuaW1nKSkNCnJhc3Rlci5wZyA8LSBhcy5yYXN0ZXIobXkucGcpDQoNCiMgVXNlIHRoZSBjb2RlIGluIHRoZSBwcmVjaW91cyBzZWN0aW9uDQpCaWxsLmxlbmd0aCA9IHBlbmd1aW5zLm5ldyRiaWxsX2xlbmd0aF9tbQ0KRmxpcHBlci5sZW5ndGggPSBhcy5udW1lcmljKHBlbmd1aW5zLm5ldyRmbGlwcGVyX2xlbmd0aF9tbSkNCnNpemUuYm9keSA9IGFzLm51bWVyaWMocGVuZ3VpbnMubmV3JEJNSSkNCg0Kc3BlY2llcyA9IHBlbmd1aW5zLm5ldyRzcGVjaWVzDQoNCiMjIGlkZW50aWZ5aW5nIHRoZSBJRCANCkFkZWxpZS5pZCA9IHdoaWNoKHNwZWNpZXM9PSJBZGVsaWUiKSAgIyB2YWx1ZSBhcmUgY2FzZSBzZW5zaXRpdmUhDQpHZW50b28uaWQgPSB3aGljaChzcGVjaWVzPT0iR2VudG9vIikNCg0KDQojIyBtYWtpbmcgYW4gZW1wdHkgcGxvdDogdHlwZSA9ICJuIiA9PT4gbm8gcG9pbnQNCnBsb3QoQmlsbC5sZW5ndGgsIEZsaXBwZXIubGVuZ3RoLCBtYWluID0gIkJpbGwgbGVnbnRoIHZzIEZsaXBwZXIgbGVnbnRoIGFjcm9zcyAyIHNwZWNpZXMiLCB0eXBlID0gIm4iICwgIHhsYWIgPSAiQmlsbCBsZWdudGggKG1tKSIsIHlsYWIgPSAiRmxpcHBlciBMZW5ndGggKG1tKSIpDQoNCnBvaW50cyhCaWxsLmxlbmd0aFtBZGVsaWUuaWRdLCBGbGlwcGVyLmxlbmd0aFtBZGVsaWUuaWRdLCANCiAgICAgICBwY2ggPSAxOSwgY29sID0gInB1cnBsZSIsIGNleCA9IHNpemUuYm9keVtBZGVsaWUuaWRdKQ0KDQpwb2ludHMoQmlsbC5sZW5ndGhbR2VudG9vLmlkXSwgRmxpcHBlci5sZW5ndGhbR2VudG9vLmlkXSwgDQogICAgICAgcGNoID0gMTksIGNvbCA9ICJuYXZ5IiwgY2V4ID0gc2l6ZS5ib2R5W0dlbnRvby5pZF0pDQoNCg0KbGVnZW5kKCJ0b3BsZWZ0IiwgYygiQWRlbGllIiwgIkdlbnRvbyIpLCANCiAgICAgICAgICAgICAgICAgIGNvbD1jKCJwdXJwbGUiLCAibmF2eSIpLA0KICAgICAgICAgICAgICAgICAgcGNoPWMoMTksIDE5KSkNCg0KI3Jhc3RlckltYWdlKHJhc3Rlci5wZyw1NywxOTAsNjAsMjIwKQ0KDQojIHBsb3QgYSByZWdyZXNzaW9uIGxpbmUgDQphYmxpbmUobG0oRmxpcHBlci5sZW5ndGhbQWRlbGllLmlkXX5CaWxsLmxlbmd0aFtBZGVsaWUuaWRdKSxjb2w9J3B1cnBsZScpIA0KDQphYmxpbmUobG0oRmxpcHBlci5sZW5ndGhbR2VudG9vLmlkXX5CaWxsLmxlbmd0aFtHZW50b28uaWRdKSxjb2w9J25hdnknKSANCmBgYCANCg0KRnJvbSBhYm92ZSB0aGUgZmlndXJlLCBtb3N0IEdlbnRvbyBwZW5ndWlucyBoYXZlIGxvbmdlciBmbGlwcGVyIGFuZCBsb25nZXIgYmlsbCB0aGFuIEFkZWxpZSBwZW5ndWlucy4gSW4gYWRkaXRpb24sIHRoZXJlIGlzIGEgcG9zaXRpdmUgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZsaXBwZXIgbGVuZ3RoIGFuZCBiaWxsIGxlbmd0aCANCmluIGJvdGggdGhlIEdlbnRvbyBhbmQgQWRlbGllIHBlbmd1aW4gc3R1ZGllcy4NCiANCiANCiANCiMgQ2FzZSBleGFtcGxlIDIgUmF3IERhdGEgVGFibGUgDQoNCiMjIERhdGEgUHJlcGFyYXRpb24NCg0KDQpUaGVyZSBhcmUgNCByYXcgZGF0YSBhdmFpbGFibGUgb24gdGhlIEdpdGh1YiB3ZWJzaXRlLCBpbmNsdWRpbmcgaW5jb21lcyBmaWxlLCBsaWZlIGV4cGVjdGFuY3kgeWVhcnMgZmlsZSwgY291bnRyaWVzIHRvdGFsIGZpbGUgYW5kIHBvcHVsYXRpb24gdG90YWwgZmlsZS4gSW4gYWRkaXRpb24saW5jb21lcyBmaWxlLCBsaWZlIGV4cGVjdGFuY3kgeWVhcnMgZmlsZSBhbmQgcG9wdWxhdGlvbiB0b3RhbCBmaWxlIGhhdmUgdG8gdHJhbnNwb3NlIGRhdGEgZmlsZXMgKGZyb20gd2lkZSB0byBsb25nKS4gVGhlbiwgY29tYmluZSB0aGUgZm91ciBmaWxlcyBpbnRvIGEgZmluYWwgZGF0YXNldCBieSB1c2luZyBQUk9DIFNRTC4NCg0KYGBge3J9DQojcmVhZCBkYXRhIGZpbGVzIGZyb20gR2l0SHViDQpJLlAuUCA9IHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vR1VBTlRTRVJOLUtVTy93ZWJjdi9tYWluL3cwNS9pbmNvbWVfcGVyX3BlcnNvbi5jc3YiKQ0KDQpMLkUuWSA9IHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vR1VBTlRTRVJOLUtVTy93ZWJjdi9tYWluL3cwNS9saWZlX2V4cGVjdGFuY3lfeWVhcnMuY3N2IikNCg0KDQpjb3VudHJ5dG90ID0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9HVUFOVFNFUk4tS1VPL3dlYmN2L21haW4vdzA1L2NvdW50cmllc190b3RhbC5jc3YiKQ0KDQoNCnBvcHRvdCA9IHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vR1VBTlRTRVJOLUtVTy93ZWJjdi9tYWluL3cwNS9wb3B1bGF0aW9uX3RvdGFsLmNzdiIpDQoNCg0KI3RyYW5zcG9zZSBkYXRhIGZyb20gd2lkZSB0byBsb25nDQoNCklQUGxvbmcgPC0gbWVsdChzZXREVChJLlAuUCksdmFsdWUubmFtZSA9ICJpbmNvbWUiLCBpZC52YXJzID0gYygiZ2VvIiksIHZhcmlhYmxlLm5hbWUgPSAieWVhciIpDQoNCkxFWWxvbmcgPC0gbWVsdChzZXREVChMLkUuWSksdmFsdWUubmFtZSA9ICJsaWZlX2V4cGVjdGFuY3kiLCBpZC52YXJzID0gYygiZ2VvIiksIHZhcmlhYmxlLm5hbWUgPSAieWVhciIpDQoNCnBvcHRvdGxvbmcgPC0gbWVsdChzZXREVChwb3B0b3QpLHZhbHVlLm5hbWUgPSAicG9wX3NpemUiLCBpZC52YXJzID0gYygiZ2VvIiksIHZhcmlhYmxlLm5hbWUgPSAieWVhciIpDQoNCg0KIyMgcmVtb3ZlIHN0cmluZyBYDQpJUFBsb25nJHllYXI8LWdzdWIoIlgiLCIiLGFzLmNoYXJhY3RlcihJUFBsb25nJHllYXIpKQ0KTEVZbG9uZyR5ZWFyPC1nc3ViKCJYIiwiIixhcy5jaGFyYWN0ZXIoTEVZbG9uZyR5ZWFyKSkNCnBvcHRvdGxvbmckeWVhcjwtZ3N1YigiWCIsIiIsYXMuY2hhcmFjdGVyKHBvcHRvdGxvbmckeWVhcikpDQoNCg0KI21lcmdlIEluY29tZSBQZXIgUGVyc29uIGFuZCBMaWZlIEV4cGVjdGFuY3kgaW4gWWVhcnMgDQpMaWZlRXhwSW5jb20gPC0gbWVyZ2UoTEVZbG9uZywgSVBQbG9uZywgYnkgPSBjKCJnZW8iLCAieWVhciIpLA0KICAgICAgICAgICAgICAgICAgICAgIGFsbCA9IFRSVUUpDQoNCiNDcmVhdGUgZGF0YWJhc2UNCmNvbiA8LSBkYkNvbm5lY3QoZHJ2ID0gU1FMaXRlKCksDQogICAgICAgICAgICAgICAgIGRibmFtZSA9ICI6bWVtb3J5OiIpDQoNCiNzdG9yZSBzYW1wbGUgZGF0YSBpbiBkYXRhYmFzZQ0KZGJXcml0ZVRhYmxlKGNvbm4gPSBjb24sIA0KICAgICAgICAgICAgIG5hbWUgPSAiTEVZbG9uZyIsDQogICAgICAgICAgICAgdmFsdWUgPSBMRVlsb25nKQ0KDQpkYldyaXRlVGFibGUoY29ubiA9IGNvbiwgDQogICAgICAgICAgICAgbmFtZSA9ICJJUFBsb25nIiwNCiAgICAgICAgICAgICB2YWx1ZSA9IElQUGxvbmcpDQoNCmRiV3JpdGVUYWJsZShjb25uID0gY29uLCANCiAgICAgICAgICAgICBuYW1lID0gIkxpZmVFeHBJbmNvbSIsDQogICAgICAgICAgICAgdmFsdWUgPSBMaWZlRXhwSW5jb20pDQoNCmRiV3JpdGVUYWJsZShjb25uID0gY29uLCANCiAgICAgICAgICAgICBuYW1lID0gImNvdW50cnl0b3QiLA0KICAgICAgICAgICAgIHZhbHVlID0gY291bnRyeXRvdCkNCg0KZGJXcml0ZVRhYmxlKGNvbm4gPSBjb24sIA0KICAgICAgICAgICAgIG5hbWUgPSAicG9wdG90bG9uZyIsDQogICAgICAgICAgICAgdmFsdWUgPSBwb3B0b3Rsb25nKQ0KDQoNCmBgYA0KDQoNCg0KDQpgYGB7c3FsLCBjb25uZWN0aW9uID0gImNvbiIsIG91dHB1dC52YXIgPSAibGlmZTIifSANCg0KU0VMRUNUIGEuKiwgYi5yZWdpb24NCkZST00gTGlmZUV4cEluY29tIEFTIEENCkxFRlQgSk9JTiBjb3VudHJ5dG90IEFTIEINCk9OIEEuZ2VvID0gQi5uYW1lOw0KDQoNCmBgYA0KDQpgYGB7cn0NCg0KI3N0b3JlIHNhbXBsZSBkYXRhIGluIGRhdGFiYXNlDQpkYldyaXRlVGFibGUoY29ubiA9IGNvbiwgDQogICAgICAgICAgICAgbmFtZSA9ICJsaWZlMiIsDQogICAgICAgICAgICAgdmFsdWUgPSBsaWZlMikNCg0KYGBgDQoNCg0KYGBge3NxbCwgY29ubmVjdGlvbiA9ICJjb24iLCBvdXRwdXQudmFyID0gImZpbmFsIn0gDQpTRUxFQ1QgYS4qLCBiLnBvcF9zaXplDQpGUk9NIGxpZmUyIEFTIEENCkxFRlQgSk9JTiBwb3B0b3Rsb25nIEFTIEINCk9OIEEuZ2VvID0gQi5nZW8gQU5EIEEueWVhciA9IEIueWVhciA7DQpgYGANCg0KYGBge3J9DQojIHdyaXRlIGZpbmFsIGRhdGEgdG8gY3N2IGZpbGUNCndyaXRlLmNzdih4ID0gZmluYWwsIGZpbGUgPSAiZmluYWwuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KDQoNCmBgYHtyfQ0KDQojIHJlYWQgZmluYWwgZmlsZQ0KZmluYWwgPSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0dVQU5UU0VSTi1LVU8vd2ViY3YvbWFpbi93MDUvZmluYWwuY3N2IikNCg0KDQpkYXRhMjAxNSA8LSBmaWx0ZXIoZmluYWwseWVhcj09MjAxNSkgICMgY3JlYXRlIDIwMTVkYXRhDQoNCmRhdGEyMDE1JHNpemUwMDAgPC0gZGF0YTIwMTUkcG9wX3NpemUvMjAwMDAwMDAgDQpgYGANCg0KDQojIyBEZXNjcmlwdGl2ZSBTdHVkeSBQdXJwb3NlICYgVmFyaWFibGVzIFJlbGF0aW9uc2hpcCANCg0KVGhlIHN0dWR5IGZvY3VzIG9uIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBpbmNvbWUgYW5kIGxpZmUgZXhwZWN0YW5jeSBhY3Jvc3MgcmVnaW9uIGluIDIwMTUuIFNlY29uZGFyeSB1bmRlcnN0YW5kaW5nIG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBpbmNvbWUgYW5kIGxpZmUgZXhwZWN0YW5jeSBvdmVyIHllYXIgaW4gZGlmZmVyZW50IHJlZ2lvbnMuIFRoZXJlIGFyZSA3IHZhcmlhYmxlcyBpbiBmaW5hbCBkYXRhc2V0LiANCg0KDQoNCi0gZ2VvIDogZ2VvZ3JhcGh5DQotIHBvcF9zaXplIDogcG9wdWxhdGlvbiBzaXplDQotIHNpemUwMDAgOiBlcXVpdmFsZW50IHJhdGlvIHRvIHBvcHVsYXRpb24gc2l6ZQ0KDQpUaGUgYmVsb3cgaXMgdGhlIGRhdGEgdGFibGUgZm9yIDIwMTUuDQoNCmBgYHtyIGV2YWw9cmVxdWlyZU5hbWVzcGFjZSgiRFQiLCBxdWlldGx5PVRSVUUpLCBlY2hvPUZBTFNFfQ0KRFQ6OmRhdGF0YWJsZSgoZGF0YTIwMTUpLCBmaWxsQ29udGFpbmVyID0gRkFMU0UsIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSA2KSkNCg0KDQpgYGANCg0KDQoNCg0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShkYXRhMjAxNSkNCg0KYGBgDQoNClBlb3BsZSB3aXRoIGEgbWF4aW11bSBpbmNvbWUgb2YgMTIwMDAwIGFuZCBhIG1pbmltdW0gaW5jb21lIG9mIDYyMyBpbiAyMDE1LiBBbHNvLCBpbiAyMDE1LCBwZW9wbGUncyBsaWZlIGV4cGVjdGFuY3kgaW5kZXggcmFuZ2VkIGZyb20gYSBoaWdoIG9mIDgzLjggdG8gYSBsb3cgb2YgNDkuNi4NCg0KIyMgICBUaGUgRGlzdHJpYnVpdGlvbiBvZiBSZWdpb24gaW4gMjAxNQ0KDQpBc2lhIGhhcyB0aGUgaGlnaGVzdCBwZXJjZW50YWdlIG9mIHRoZSB3b3JsZCdzIHBvcHVsYXRpb24gKDI4LjUlKSwgd2l0aCBhIHRvdGFsIG9mIDUxIGNvdW50cmllcy4gT2NlYW5pYSBoYXMgdGhlIGxvd2VzdCBwZXJjZW50YWdlIG9mIHRoZSB3b3JsZCdzIHBvcHVsYXRpb24gKDcuMjYlKSwgd2l0aCBhIHRvdGFsIG9mIDEzIGNvdW50cmllcy4NCg0KYGBge3J9DQpwaWVkYXRhIDwtIGZpbHRlcihkYXRhMjAxNSwhaXMubmEocmVnaW9uKSkNCg0KcGllZGF0YWYgPSBkYXRhLmZyYW1lKGNhdGUgPWFzLnZlY3Rvcih1bmlxdWUocGllZGF0YSRyZWdpb24pKSwgDQogICAgICAgICAgICAgICAgICAgICBmcmVxID0gYXMudmVjdG9yKHRhYmxlKHBpZWRhdGEkcmVnaW9uKSkpDQoNCiMgZGVmaW5lIGEgY29sb3IgdmVjdG9yDQpjb2xvcnMgPC0gYygncmdiKDIxMSw5NCw5NiknLCAncmdiKDEyOCwxMzMsMTMzKScsICdyZ2IoMTQ0LDEwMywxNjcpJykNCiMgbWFrZSBhIHBpZSBjaGFydA0KcGxvdF9seShwaWVkYXRhZiwgDQogICAgICAgIGxhYmVscyA9IH5jYXRlLCANCiAgICAgICAgdmFsdWVzID0gfmZyZXEsIA0KICAgICAgICB0eXBlID0gJ3BpZScsDQogICAgICAgIHRleHRwb3NpdGlvbiA9ICdpbnNpZGUnLA0KICAgICAgICB0ZXh0aW5mbyA9ICdsYWJlbCArIHBlcmNlbnQnLA0KICAgICAgICBpbnNpZGV0ZXh0Zm9udCA9IGxpc3QoY29sb3IgPSAnI0ZGRkZGRicpLA0KICAgICAgICAjaG92ZXJpbmZvID0gJ3RleHQnLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9ycyA9IGNvbG9ycywNCiAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjRkZGRkZGJywgd2lkdGggPSAxKSksDQogICAgICAgICAgICAgICAgICAgICAgI1RoZSAncHVsbCcgYXR0cmlidXRlIGNhbiBhbHNvIGJlIHVzZWQgdG8gY3JlYXRlIHNwYWNlIGJldHdlZW4gdGhlIHNlY3RvcnMNCiAgICAgICAgc2hvd2xlZ2VuZCA9IFRSVUUpICU+JSANCiAgICAgICAgIGxheW91dCh0aXRsZSA9ICdEaXN0cmlidXRpb24gb2YgUmVnaW9uIGluIDIwMTUnLA0KICAgICAgICAgICAgICAgIHhheGlzID0gbGlzdChzaG93Z3JpZCA9IEZBTFNFLCB6ZXJvbGluZSA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSksDQogICAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KHNob3dncmlkID0gRkFMU0UsIHplcm9saW5lID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93dGlja2xhYmVscyA9IEZBTFNFKSwNCiAgICAgICAgICAgICAgICAgICAgICAjIyBtYXJnaW4gb2YgdGhlIHBsb3QNCiAgICAgIG1hcmdpbiA9IGxpc3QoDQogICAgICAgICAgICAgIGIgPSA1MCwNCiAgICAgICAgICAgICAgbCA9IDEwMCwNCiAgICAgICAgICAgICAgdCA9IDEyMCwNCiAgICAgICAgICAgICAgciA9IDUwDQogICAgICApKQ0KYGBgDQoNCiMjICAgVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEluY29tZSBhbmQgTGlmZSBFeHBlY3RhbmN5IGFjcm9zcyBSZWdpb24gaW4gMjAxNQ0KDQoNCk1vc3QgcGVvcGxlIGluIHRoZSBFdXJvcGVhbiByZWdpb24gaGF2ZSBoaWdoZXIgaW5jb21lcyBhbmQgaGlnaGVyIGxldmVscyBvZiBsaWZlIGV4cGVjdGFuY3kuIEFuZCBtb3N0IHBlb3BsZSBpbiB0aGUgQWZyaWNhbiByZWdpb24gaGF2ZSBsb3dlciBpbmNvbWVzIGFuZCBsb3dlciBsZXZlbHMgb2YgbGlmZSBleHBlY3RhbmN5Lg0KDQoNCmBgYHtyfQ0KDQpwbG90X2x5KA0KICAgIGRhdGEgPSBkYXRhMjAxNSwNCiAgICB4ID0gfmluY29tZSwgICMgSG9yaXpvbnRhbCBheGlzIA0KICAgIHkgPSB+bGlmZV9leHBlY3RhbmN5LCAgICMgVmVydGljYWwgYXhpcyANCiAgICBjb2xvciA9IH5mYWN0b3IocmVnaW9uKSwgICMgbXVzdCBiZSBhIG51bWVyaWMgZmFjdG9yDQogICAgDQogICAgI3RleHQgPSB+U3BlY2llcywNCiAgICB0ZXh0ID0gfnBhc3RlKCJjb3VudHJ5IG5hbWU6ICIsIGdlbywNCiAgICAgICAgICAgICAgICAgICAiPGJyPnBvcHVsYXRpb24gc2l6ZTogIiwgcG9wX3NpemUsDQogICAgICAgICAgICAgICAgICAgIjxicj5yZWdpb246ICIsIHJlZ2lvbiksIA0KICAgICAjIFNob3cgdGhlIHNwZWNpZXMgaW4gdGhlIGhvdmVyIHRleHQNCiAgICAgIyMgdXNpbmcgdGhlIGZvbGxvd2luZyBob3ZlcnRlbXBsYXRlKCkgdG8gYWRkIHRoZSBpbmZvcm1hdGlvbiBvZiB0aGUNCiAgICAgIyMgVHdvIG51bWVyaWNhbCB2YXJpYWJsZXMgdG8gdGhlIGhvdmVyIHRleHQuDQogICAgICMjIyBVc2UgdGhlIGZvbGxvd2luZyBob3ZlciB0ZW1wbGF0ZSB0byBkaXNwbGF5IG1vcmUgaW5mb3JtYXRpb24NCiAgICAgaG92ZXJ0ZW1wbGF0ZSA9IHBhc3RlKCc8aT48Yj5saWZlIGV4cGVjdGFuY3k8Yj48L2k+OiAle3l9JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+PGI+aW5jb21lPC9iPjogICV7eH0nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj48Yj4le3RleHR9PC9iPicpLA0KICAgICBhbHBoYSAgPSAwLjYsDQogICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IH5zaXplMDAwLCBzaXplcmVmID0gLjA1LCBzaXplbW9kZSA9ICdhcmVhJyApLA0KICAgICB0eXBlID0gInNjYXR0ZXIiLA0KICAgICBtb2RlID0gIm1hcmtlcnMiLA0KICAgICAjIyBncmFwaGljIHNpemUNCiAgICAgd2lkdGggPSA3MDAsDQogICAgIGhlaWdodCA9IDUwMCkgJT4lDQogICAgbGF5b3V0KCAgDQogICAgICAjIyMgVGl0bGUgDQogICAgICB0aXRsZSA9bGlzdCh0ZXh0ID0gIkluY29tZSB2cyBMaWZlIEV4cGVjdGFuY3kgaW4gMjAxNSIsIA0KICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gIlRpbWVzIE5ldyBSb21hbiIsICAjIEhUTUwgZm9udCBmYW1pbHkgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIikpLCANCiAgICAgICMjIyBsZWdlbmQNCiAgICAgIGxlZ2VuZCA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQgPSAncmVnaW9uJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJDb3VyaWVyIE5ldyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmVlbiIpKSwNCiAgICAgICAgICAgICAgICAgICAgYmdjb2xvciA9ICJpdm9yeSIsDQogICAgICAgICAgICAgICAgICAgIGJvcmRlcmNvbG9yID0gIm5hdnkiLA0KICAgICAgICAgICAgICAgICAgICBncm91cGNsaWNrID0gInRvZ2dsZWdyb3VwIiwgICMgb25lIG9mICAidG9nZ2xlaXRlbSIgQU5EICJ0b2dnbGVncm91cCIuDQogICAgICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uID0gInYiICAjIFNldHMgdGhlIG9yaWVudGF0aW9uIG9mIHRoZSBsZWdlbmQuDQogICAgICAgICAgICAgICAgICAgICksDQogICAgICAjIyBtYXJnaW4gb2YgdGhlIHBsb3QNCiAgICAgIG1hcmdpbiA9IGxpc3QoDQogICAgICAgICAgICAgIGIgPSAxMDAsDQogICAgICAgICAgICAgIGwgPSAxMDAsDQogICAgICAgICAgICAgIHQgPSA1MCwNCiAgICAgICAgICAgICAgciA9IDUwDQogICAgICApLA0KICAgICAgIyMgQmFja2dyb3VuZA0KICAgICAgcGxvdF9iZ2NvbG9yID0nI2Y3ZjdmNycsIA0KICAgICAgIyMgQXhlcyBsYWJlbHMNCiAgICAgICAgICAgICB4YXhpcyA9IGxpc3QoIA0KICAgICAgICAgICAgICAgICAgICB0aXRsZT1saXN0KHRleHQgPSAnSW5jb21lJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAnQXJpYWwnKSksDQogICAgICAgICAgICAgICAgICAgIHplcm9saW5lY29sb3IgPSAncmVkJywgDQogICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLCANCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJyksIA0KICAgICAgICAgICAgeWF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0xpZmUgRXhwZWN0YW5jeScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ0FyaWFsJykpLA0KICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZWNvbG9yID0gJ3B1cnBsZScsIA0KICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZXdpZHRoID0gMiwgDQogICAgICAgICAgICAgICAgICAgIGdyaWRjb2xvciA9ICd3aGl0ZScpLA0KICAgICAgICMjIGFubm90YXRpb25zDQogICAgICAgYW5ub3RhdGlvbnMgPSBsaXN0KCAgDQogICAgICAgICAgICAgICAgICAgICB4ID0gMC41LCAgICMgYmV0d2VlbiAwIGFuZCAxLiAwID0gbGVmdCwgMSA9IHJpZ2h0DQogICAgICAgICAgICAgICAgICAgICB5ID0gMS41LCAgICMgYmV0d2VlbiAwIGFuZCAxLCAwID0gYm90dG9tLCAxID0gdG9wDQogICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChzaXplID0gMTIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiksICAgDQogICAgICAgICAgICAgICAgICB0ZXh0ID0gIlRoZSBwb2ludCBzaXplIGlzIHByb3BvcnRpb25hbCB0byB0aGUgcG9wdWxhdGlvbiBzaXplIiwgICANCiAgICAgICAgICAgICAgICAgIHhyZWYgPSAicGFwZXIiLCAgIyAiY29udGFpbmVyIiBzcGFucyB0aGUgZW50aXJlIGB3aWR0aGAgb2YgdGhlIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICBsb3QuICJwYXBlciIgcmVmZXJzIHRvIHRoZSB3aWR0aCBvZiB0aGUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIHBsb3R0aW5nIGFyZWEgb25seS4geXJlZiA9ICJwYXBlciIsICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgc2FtZSBhcyB4cmVmLg0KICAgICAgICAgICAgICAgeGFuY2hvciA9ICJjZW50ZXIiLCAjICBob3Jpem9udGFsIGFsaWdubWVudCB3aXRoIHJlc3BlY3QgdG8gaXRzIHggcG9zaXRpb24NCiAgICAgICAgICAgICAgIHlhbmNob3IgPSAiYm90dG9tIiwgIyAgc2ltaWxhciB0byB4YW5jaG9yICANCiAgICAgICAgICAgICBzaG93YXJyb3cgPSBGQUxTRSkNCiAgICANCiAgICAgDQogICAgDQogICAgKSANCg0KYGBgDQojIyAgIFRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBJbmNvbWUgYW5kIExpZmUgRXhwZWN0YW5jeSBhY3Jvc3MgUmVnaW9uIG92ZXIgdGhlIHllYXJzICANCg0KVGhlIGxpZmUgZXhwZWN0YW5jeSBvZiBwZW9wbGUgaW4gdGhlIGFsbCByZWdpb25zIGhhcyBpbmNyZWFzZWQgd2l0aCBlYWNoIHBhc3NpbmcgeWVhci4gSW4gMTgwMCwgbW9zdCBvZiBFdXJvcGUgaGFkIGEgaGlnaGVyIGxldmVsIG9mIGxpZmUgZXhwZWN0YW5jeS4gSG93ZXZlciwgaW4gMjAxOCwgaGlnaGVyIGxldmVscyBvZiBsaWZlIGV4cGVjdGFuY3kgbWF5IGNvbWUgZnJvbSAgbXVsdGlwbGUgcmVnaW9uYWwgb2YgY291bnRyeS4gQXMgY2FuIGJlIHNlZW4gZnJvbSB0aGUgZmlndXJlLCB0aGVyZSBpcyBhIHBvc2l0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiBpbmNvbWUgYW5kIGxldmVscyBvZiBsaWZlIGV4cGVjdGFuY3kgYWNyb3NzIHJlZ2lvbnMuDQpgYGB7cn0gDQoNCnBhbC5JQk0gPC0gYygiIzMzMjI4OCIsICIjMTE3NzMzIiwgIiMwMDcyQjIiLCIjRDU1RTAwIiwgIiM4ODIyNTUiKQ0KcGFsLklCTSA8LSBzZXROYW1lcyhwYWwuSUJNLCBjKCJBc2lhIiwgIkV1cm9wZSIsICJBZnJpY2EiLCAiQW1lcmljYXMiLCAiT2NlYW5pYSIpKQ0KDQpkZiA8LSBmaWx0ZXIoZmluYWwsIWlzLm5hKHJlZ2lvbikpDQoNCiNkZiA8LSBmaW5hbCANCmZpZyA8LSBkZiAlPiUNCiAgcGxvdF9seSgNCiAgICB4ID0gfmluY29tZSwgDQogICAgeSA9IH5saWZlX2V4cGVjdGFuY3ksIA0KICAgIHNpemUgPSB+KDIqbG9nKHBvcF9zaXplKS0xMSleMiwNCiAgICBjb2xvciA9IH5yZWdpb24sIA0KICAgIGNvbG9ycyA9IHBhbC5JQk0sICAgIyBjdXN0b20gY29sb3JzDQogICAgI21hcmtlciA9IGxpc3Qoc2l6ZSA9IH4obG9nKHBvcCktMTApLCAgc2l6ZW1vZGUgPSAnYXJlYScpLA0KICAgIGZyYW1lID0gfnllYXIsICAgICAgIyB0aGUgdGltZSB2YXJpYWJsZSB0bw0KICAgICMgdG8gZGlzcGxheSBpbiB0aGUgaG92ZXINCiAgICB0ZXh0ID0gfnBhc3RlKCJDb3VudHJ5OiIsIGdlbywNCiAgICAgICAgICAgICAgICAgICI8YnI+UmVnaW9uOiIsIHJlZ2lvbiwNCiAgICAgICAgICAgICAgICAgICI8YnI+WWVhcjoiLCB5ZWFyLA0KICAgICAgICAgICAgICAgICAgIjxicj5MaWZlRXhwOiIsIGxpZmVfZXhwZWN0YW5jeSwNCiAgICAgICAgICAgICAgICAgICI8YnI+UG9wOiIsIHBvcF9zaXplKSwNCiAgICBob3ZlcmluZm8gPSAidGV4dCIsDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ21hcmtlcnMnDQogICkNCmZpZyA8LSBmaWcgJT4lIGxheW91dCgNCiAgICB4YXhpcyA9IGxpc3QoDQogICAgICB0eXBlID0gImxvZyINCiAgICApLA0KICAgIA0KICAgICAgdGl0bGUgPWxpc3QodGV4dCA9ICJJbmNvbWUgdnMgTGlmZSBFeHBlY3RhbmN5IG92ZXIgdGhlIHllYXJzIiwgDQogICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiVGltZXMgTmV3IFJvbWFuIiwgICMgSFRNTCBmb250IGZhbWlseSAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxOCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiKSksDQogICAgDQogICAgICB4YXhpcyA9IGxpc3QoIA0KICAgICAgICAgICAgICAgICAgICB0aXRsZT1saXN0KHRleHQgPSAnSW5jb21lJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAnQXJpYWwnKSksDQogICAgICAgICAgICAgICAgICAgIHplcm9saW5lY29sb3IgPSAncmVkJywgDQogICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLCANCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJyksIA0KICAgICAgICAgICAgeWF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0xpZmUgRXhwZWN0YW5jeScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ0FyaWFsJykpLA0KICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZWNvbG9yID0gJ3B1cnBsZScsIA0KICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZXdpZHRoID0gMiwgDQogICAgICAgICAgICAgICAgICAgIGdyaWRjb2xvciA9ICd3aGl0ZScpDQogICkNCg0KZmlnDQpgYGANCg0KDQo=